import express, { NextFunction, Request, Response } from "express";
import { Express } from "express";
import { initDB } from "./db/sync";
import { CustomResponse } from "./middleware/error";
import path from "path";
import cookieParser from "cookie-parser";
import Joi from "@hapi/joi";
import cors from "cors";

// token
import { expressjwt } from "express-jwt";
// 路由导入
// import UserRouter from './routes/user'

const app = express();
const port = 4000;

(async () => {
  try {
    // 调用 initDB 函数来同步数据库
    // await initDB();
    // 中间件

    // 挂载自定义错误处理中间件
    app.use((await import("./middleware/error")).errorHandler);

    // 配置跨域
    const whiteList = [
      "http://localhost:4000",
      "http://127.0.0.1:3000",
      "http://localhost:8080",
      "null",
    ];
    // postman/electron 等非浏览器环境 无origin或为null
    app.use(
      cors({
        origin: (origin: string, callback) => {
          if (!origin || whiteList.includes(origin)) {
            callback(null, origin);
          } else {
            callback(null, false);
          }
        },
      }),
    );

    // res注入操作cookie的函数
    app.use(cookieParser("secret"));
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));

    // 除 /user 其他都需要token
    app.use(
      expressjwt({
        secret: (await import("./config")).default.secret,
        algorithms: ["HS256"], // 算法数组 必须
      }).unless({
        path: [
          "/user/login",
          "/user/reg",
          /^\/test/,
          /^\/uploads/,
          /^\/static/,
        ],
      }),
    );
    // 静态资源
    app.use("/static", express.static(path.join(__dirname, "./public")));
    app.use("/uploads", express.static(path.join(__dirname, "./uploads")));

    // 路由
    app.get("/", (req, res) => {
      res.send("Hello World!");
    });

    // app.use("/upload", (await import("./routes/upload")).default);

    app.use("/user", (await import("./routes/user")).default); // 外有saync
    app.use("/test", (await import("./routes/test")).default);

    // 错误处理中间件
    app.use(
      (err: Error, req: Request, res: CustomResponse, next: NextFunction) => {
        // joi数据验证失败
        if (err instanceof Joi.ValidationError) return res.cc(err);
        // 捕获token身份认证失败的错误
        if (err.name === "UnauthorizedError") return res.cc("身份认证失败！");
        // 未知错误
        res.cc(err);
      },
    );

    // 启动 Express 应用
    app.listen(port, () => {
      console.log(`Example app listening at http://localhost:${port}`);
    });
  } catch (error) {
    console.error("数据库同步失败:", error);
    process.exit(1); // 如果同步失败，退出进程
  }
})();
